import config from '@/config/index.js';
import { globalAutoLogin, refreshTokenFn } from './auth.js';
import store from '@/store/index.js';

// 配置基本请求地址
const baseURL = config.baseURL;
// 固定API前缀
const API_PREFIX = '/app-api';

// 登录状态标记，防止多个请求同时触发登录
let isLoginInProgress = false;
// 请求队列，用于存储401时的请求
let requestQueue = [];
// 自动登录冷却时间（毫秒）
const AUTO_LOGIN_COOLDOWN = 10000;
// 上次自动登录时间
let lastAutoLoginTime = 0;

// 消息提示方法
const showToast = (message) => {
  uni.showToast({
    title: message,
    icon: 'none',
    duration: 2000
  });
};

/**
 * 自动登录方法
 * @returns {Promise<boolean>} 是否登录成功
 */
const autoLogin = async () => {
  try {
    // 检查冷却时间
    const now = Date.now();
    if (now - lastAutoLoginTime < AUTO_LOGIN_COOLDOWN) {
      console.log('自动登录冷却中，跳过此次登录尝试');
      return false;
    }
    
    // 更新最后登录时间
    lastAutoLoginTime = now;
    
    console.log('接口返回401，尝试全局自动登录...');
    
    // 调用全局登录方法，确保全局只有一个登录流程
    return await globalAutoLogin();
  } catch (error) {
    console.error('自动登录失败:', error);
    return false;
  }
};

/**
 * 处理请求队列中的请求
 */
const processRequestQueue = () => {
  const queue = [...requestQueue];
  requestQueue = [];
  
  console.log(`处理请求队列，共${queue.length}个请求`);
  
  queue.forEach((item, index) => {
    const { options, resolve, reject, isUpload } = item;
    console.log(`处理队列请求 #${index+1}:`, options.url);
    
    // 获取新token
    const token = uni.getStorageSync('token');
    if (token) {
      options.header.Authorization = 'Bearer ' + token;
    }
    
    // 区分普通请求和上传请求
    if (isUpload) {
      // 重新发起上传请求
      const uploadTask = uni.uploadFile({
        ...options,
        success: (res) => {
          console.log(`队列上传请求 #${index+1} 完成:`, options.url);
          try {
            // 解析响应数据
            if (typeof res.data === 'string') {
              res.data = JSON.parse(res.data);
            }
            
            // 处理响应
            if (res.statusCode >= 200 && res.statusCode < 300) {
              if (res.data.code === 0) {
                resolve(res.data.data);
              } else {
                showToast(res.data.msg || '上传失败');
                reject(res.data);
              }
            } else {
              showToast(`上传错误: ${res.statusCode}`);
              reject(res);
            }
          } catch (e) {
            console.error('处理上传响应出错:', e);
            reject(new Error('上传响应解析失败'));
          }
        },
        fail: (err) => {
          console.error(`队列上传请求 #${index+1} 失败:`, options.url, err);
          showToast('文件上传失败');
          reject(err);
        }
      });
      
      // 恢复进度监听
      if (options.onProgress && uploadTask) {
        uploadTask.onProgressUpdate((res) => {
          options.onProgress(res.progress);
        });
      }
    } else {
      // 重新发起普通请求
      uni.request({
        ...options,
        success: (res) => {
          console.log(`队列请求 #${index+1} 完成:`, options.url);
          handleResponse(res, resolve, reject, options);
        },
        fail: (err) => {
          console.error(`队列请求 #${index+1} 失败:`, options.url, err);
          showToast('网络请求失败');
          reject(err);
        }
      });
    }
  });
};

/**
 * 统一处理响应
 */
const handleResponse = async (res, resolve, reject, options) => {
  // 基于后端API返回格式统一处理响应
  if (res.statusCode >= 200 && res.statusCode < 300) {
    // 后端返回的数据格式是 { code: 0, data: xxx, msg: 'xxx' }
    if (res.data.code === 0) {
      resolve(res.data.data);
    } else if (res.data.code === 401) {
      // 处理后端返回的业务状态码为401的情况（账号未登录）
      console.log('接收到业务code为401的未授权响应:', res.data.msg);
      
      // 处理未登录状态，与statusCode为401的处理逻辑相同
      await handleUnauthorized(res, options, resolve, reject);
    } else {
      // 其他业务错误
      // showToast(res.data.msg || '请求失败');
      reject(res.data);
    }
  } else if (res.statusCode === 401) {
    console.log('接收到HTTP状态码401的未授权响应');
    
    // 处理未登录状态
    await handleUnauthorized(res, options, resolve, reject);
  } else {
    // 其他HTTP错误
    showToast(`网络错误: ${res.statusCode}`);
    reject(res);
  }
};

/**
 * 处理未授权/未登录的情况
 * @param {Object} res - 响应对象
 * @param {Object} options - 请求选项
 * @param {Function} resolve - Promise的resolve函数
 * @param {Function} reject - Promise的reject函数
 * @param {Boolean} isUpload - 是否是上传请求
 */
const handleUnauthorized = async (res, options, resolve, reject, isUpload = false) => {
  // 将当前请求添加到队列，使用URL和参数作为唯一标识
  const requestId = isUpload ? 
    options.url + (options.filePath || '') : 
    options.url + JSON.stringify(options.data);
  
  // 检查队列中是否已存在相同请求
  const isAlreadyQueued = requestQueue.some(item => 
    (isUpload && item.isUpload) ? 
      item.options.url === options.url && item.options.filePath === options.filePath :
      item.options.url === options.url && JSON.stringify(item.options.data) === JSON.stringify(options.data)
  );
  
  if (!isAlreadyQueued) {
    console.log(`将${isUpload ? '上传' : ''}请求加入队列: ${options.url}`);
    requestQueue.push({
      options,
      resolve,
      reject,
      requestId,
      isUpload
    });
  } else {
    console.log(`请求已在队列中: ${options.url}`);
  }
  
  // 如果已经有登录进行中，不再重复触发登录
  if (isLoginInProgress) {
    console.log('已有登录流程进行中，当前请求已加入队列，等待处理');
    return;
  }
  
  // 设置登录状态为进行中
  isLoginInProgress = true;
  
  try {
    // 先尝试使用refreshToken刷新token
    const refreshToken = uni.getStorageSync('refreshToken');
    if (refreshToken) {
      try {
        console.log('尝试刷新token...');
        // 调用refreshTokenFn获取新token
        await refreshTokenFn();
        console.log('token刷新成功，更新用户信息并处理请求队列');
        
        // 尝试更新用户信息
        try {
          const store = require('@/store').default;
          await store.dispatch('user/getUserInfo');
        } catch (userInfoError) {
          console.warn('刷新token后获取用户信息失败，继续处理请求:', userInfoError);
          // 虽然获取用户信息失败，但不影响请求继续处理
        }
        
        // 重置登录状态
        isLoginInProgress = false;
        
        // 处理请求队列
        processRequestQueue();
        return;
      } catch (refreshError) {
        console.error('刷新token失败，尝试自动登录:', refreshError);
        // 清除登录状态和token
        const store = require('@/store').default;
        store.commit('user/CLEAR_USER_INFO');
        uni.removeStorageSync('token');
        uni.removeStorageSync('refreshToken');
        uni.removeStorageSync('tokenExpire');
        // 刷新token失败，继续尝试自动登录
      }
    } else {
      console.log('没有refreshToken，直接尝试自动登录');
    }
    
    // 尝试自动登录（内部会使用全局登录方法，确保不重复登录）
    const loginSuccess = await autoLogin();
    
    // 登录流程完成，重置状态
    isLoginInProgress = false;
    
    if (loginSuccess) {
      // 登录成功，处理之前的请求队列
      processRequestQueue();
    } else {
      // 自动登录失败，清空队列，跳转到登录页
      requestQueue = [];
      
      // 如果是因为冷却期而跳过登录，不显示提示和跳转，直接拒绝当前请求
      const now = Date.now();
      if (now - lastAutoLoginTime >= AUTO_LOGIN_COOLDOWN) {
        showToast('请重新登录');
        // 清除本地token
        uni.removeStorageSync('token');
        setTimeout(() => {
          uni.redirectTo({
            url: '/pages/login/login'
          });
        }, 1500);
      }
      
      reject(res.data);
    }
  } catch (error) {
    isLoginInProgress = false;
    requestQueue = [];
    showToast('登录异常，请重试');
    reject(error);
  }
};

/**
 * 封装请求方法
 * @param {Object} options - 请求配置项
 * @returns {Promise} 返回请求结果Promise
 */
const request = (options = {}) => {
  // 合并选项
  options.url = baseURL + API_PREFIX + (options.url.startsWith('/') ? options.url : `/${options.url}`);
  options.method = options.method || 'GET';
  options.header = options.header || {};
  options.data = options.data || {};
  options.timeout = options.timeout || config.timeout;
  
  // 获取本地token
  const token = uni.getStorageSync('token');
  if (token) {
    options.header.Authorization = 'Bearer ' + token;
  }
  
  // 添加租户标识（优先从本地存储获取，没有再使用config）
  const tenantId = uni.getStorageSync('tenantId') || config.tenantId;
  options.header['tenant-id'] = tenantId;
  
  // 返回Promise
  return new Promise((resolve, reject) => {
    uni.request({
      ...options,
      success: (res) => handleResponse(res, resolve, reject, options),
      fail: (err) => {
        showToast('网络请求失败');
        reject(err);
      }
    });
  });
};

// 提供常用请求方法
const api = {
  get: (url, data = {}, options = {}) => {
    return request({
      url,
      data,
      method: 'GET',
      ...options
    });
  },
  post: (url, data = {}, options = {}) => {
    return request({
      url,
      data,
      method: 'POST',
      ...options
    });
  },
  put: (url, data = {}, options = {}) => {
    return request({
      url,
      data,
      method: 'PUT',
      ...options
    });
  },
  delete: (url, data = {}, options = {}) => {
    return request({
      url,
      data,
      method: 'DELETE',
      ...options
    });
  },
  
  /**
   * 上传文件的统一方法，包含统一的鉴权、错误处理和重试机制
   * @param {Object} options - 上传选项
   * @param {String} options.url - 上传接口地址
   * @param {String} options.filePath - 文件路径
   * @param {String} options.name - 文件对应的 key，默认为 'file'
   * @param {Object} options.formData - 附加的表单数据
   * @param {Function} options.onProgress - 上传进度回调
   * @returns {Promise} 上传结果
   */
  uploadFile: (options = {}) => {
    // 合并选项
    options.url = baseURL + API_PREFIX + (options.url.startsWith('/') ? options.url : `/${options.url}`);
    options.name = options.name || 'file';
    options.formData = options.formData || {};
    options.header = options.header || {};
    
    // 获取本地token
    const token = uni.getStorageSync('token');
    if (token) {
      options.header.Authorization = 'Bearer ' + token;
    }
    
    // 添加租户标识（优先从本地存储获取，没有再使用config）
    const tenantId = uni.getStorageSync('tenantId') || config.tenantId;
    options.header['tenant-id'] = tenantId;
    
    // 返回Promise
    return new Promise((resolve, reject) => {
      const uploadTask = uni.uploadFile({
        ...options,
        success: (res) => {
          try {
            // 解析响应数据
            if (typeof res.data === 'string') {
              res.data = JSON.parse(res.data);
            }
            
            // 处理响应，和request方法保持一致的逻辑
            if (res.statusCode >= 200 && res.statusCode < 300) {
              // 业务成功
              if (res.data.code === 0) {
                resolve(res.data.data);
              } else if (res.data.code === 401) {
                // 处理未授权情况，将当前上传请求加入重试队列
                console.log('上传接口返回401未授权');
                
                // 将上传请求添加到队列
                const requestId = options.url + (options.filePath || '');
                const isAlreadyQueued = requestQueue.some(item => 
                  item.requestId === requestId
                );
                
                if (!isAlreadyQueued) {
                  console.log(`将上传请求加入队列: ${options.url}`);
                  requestQueue.push({
                    options,
                    resolve,
                    reject,
                    requestId,
                    isUpload: true // 标记为上传请求
                  });
                  
                  // 触发自动登录流程
                  if (!isLoginInProgress) {
                    isLoginInProgress = true;
                    autoLogin().then(success => {
                      isLoginInProgress = false;
                      if (success) {
                        processRequestQueue();
                      } else {
                        requestQueue = [];
                        showToast('请重新登录');
                        reject(res.data);
                      }
                    }).catch(error => {
                      isLoginInProgress = false;
                      requestQueue = [];
                      showToast('登录异常，请重试');
                      reject(error);
                    });
                  }
                }
              } else {
                // 其他业务错误
                showToast(res.data.msg || '上传失败');
                reject(res.data);
              }
            } else if (res.statusCode === 401) {
              // 处理HTTP 401状态码，与业务401逻辑相同
              console.log('上传接口HTTP状态401未授权');
              handleUnauthorized(res, options, resolve, reject, true);
            } else {
              // 其他HTTP错误
              showToast(`上传错误: ${res.statusCode}`);
              reject(res);
            }
          } catch (e) {
            console.error('处理上传响应出错:', e);
            reject(new Error('上传响应解析失败'));
          }
        },
        fail: (err) => {
          showToast('文件上传失败');
          reject(err);
        }
      });
      
      // 处理上传进度
      if (options.onProgress && uploadTask) {
        uploadTask.onProgressUpdate((res) => {
          options.onProgress(res.progress);
        });
      }
    });
  },
  
  /**
   * 获取包含认证信息的请求头
   * @returns {Object} 请求头对象
   */
  getTokenHeader() {
    // 优先从本地存储获取租户ID，没有再使用config
    const tenantId = uni.getStorageSync('tenantId') || config.tenantId;
    const headers = {
      'tenant-id': tenantId
    };
    
    // 获取本地token
    const token = uni.getStorageSync('token');
    if (token) {
      headers.Authorization = 'Bearer ' + token;
    }
    
    return headers;
  },
  
  // 导出基础URL，用于构建完整URL
  baseURL: baseURL + API_PREFIX
};

export default api; 